package com.modbus.util;


import com.modbus.constant.ModbusConstants;
import com.modbus.entity.exception.DataConvertException;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;

/**
 * @author heyayun
 * @description 数据转换
 * @date 2021/3/26 11:10
 */
@Slf4j
public class HexUtil {
    /**
     * 进制16
     */
    public static final int HEX_16 = 16;

    /**
     * String数组转byte数组
     *
     * @param args
     * @return
     * @throws DataConvertException
     */
    public static byte[] strToByte(String[] args) throws DataConvertException {
        if (args == null) {
            throw new DataConvertException("String数组转byte数组,args不可为空!!");
        }
        byte[] bytes = new byte[args.length];
        for (int i = 0; i < args.length; i++) {
            bytes[i] = hexToByte(args[i]);
        }
        return bytes;
    }

    /**
     * Hex转byte,hex只能含两个字符
     * 如果是一个字符byte高位会是0
     *
     * @param hex
     * @return
     * @throws DataConvertException
     */
    public static byte hexToByte(String hex) throws DataConvertException {
        if (StringUtils.isEmpty(hex)) {
            throw new DataConvertException("Hex转byte,hex不可为空!!");
        }
        try {
            return (byte) Integer.parseInt(hex, HEX_16);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new DataConvertException("Hex转byte转换错误!!");
        }
    }

    /**
     * Hex转byte[]，两种情况，Hex长度为奇数最后一个字符会被舍去
     *
     * @param hex
     * @return
     */
    public static byte[] hexToBytes(String hex) {
        if (hex.length() < 1) {
            return null;
        } else {
            byte[] result = new byte[hex.length() / 2];
            int j = 0;
            for (int i = 0; i < hex.length(); i += 2) {
                result[j++] = (byte) Integer.parseInt(hex.substring(i, i + 2), HEX_16);
            }
            return result;
        }
    }


    /**
     * 字符串转换成十六进制字符串
     *
     * @param str 待转换的ASCII字符串
     * @return String 每个Byte之间空格分隔，如: [61 6C 6B]
     */
    public static String str2HexStr(String str) {

        char[] chars = "0123456789ABCDEF".toCharArray();
        StringBuilder sb = new StringBuilder("");
        byte[] bs = str.getBytes();
        int bit;

        for (byte b : bs) {
            bit = (b & 0x0f0) >> 4;
            sb.append(chars[bit]);
            bit = b & 0x0f;
            sb.append(chars[bit]);
            sb.append(' ');
        }
        return sb.toString().trim();
    }

    /**
     * 十六进制转换字符串
     *
     * @param hexStr Byte字符串(Byte之间无分隔符 如:[616C6B])
     * @return String 对应的字符串
     */
    public static String hexStr2Str(String hexStr) {
        String str = "0123456789ABCDEF";
        char[] hexs = hexStr.toCharArray();
        byte[] bytes = new byte[hexStr.length() / 2];
        int n;

        for (int i = 0; i < bytes.length; i++) {
            n = str.indexOf(hexs[2 * i]) * HEX_16;
            n += str.indexOf(hexs[2 * i + 1]);
            bytes[i] = (byte) (n & 0xff);
        }
        return new String(bytes);
    }

    /**
     * bytes转换成十六进制字符串
     *
     * @param b byte数组
     * @return String 每个Byte值之间空格分隔
     */
    public static String byte2HexStr(byte[] b) {
        String stmp = "";
        StringBuilder sb = new StringBuilder("");
        for (byte value : b) {
            stmp = Integer.toHexString(value & 0xFF);
            sb.append((stmp.length() == 1) ? "0" + stmp : stmp);
        }
        return sb.toString().toUpperCase().trim();
    }

    /**
     * bytes字符串转换为Byte值
     *
     * @param src Byte字符串，每个Byte之间没有分隔符
     * @return byte[]
     */
    public static byte[] hexStr2Bytes(String src) {
        int m = 0, n = 0;
        int l = src.length() / 2;
        System.out.println(l);
        byte[] ret = new byte[l];
        for (int i = 0; i < l; i++) {
            m = i * 2 + 1;
            n = m + 1;
            ret[i] = Byte.decode("0x" + src.substring(i * 2, m) + src.substring(m, n));
        }
        return ret;
    }

    /**
     * String的字符串转换成unicode的String
     *
     * @param strText 全角字符串
     * @return String 每个unicode之间无分隔符
     */
    public static String strToUnicode(String strText) {
        char c;
        StringBuilder str = new StringBuilder();
        int intAsc;
        String strHex;
        for (int i = 0; i < strText.length(); i++) {
            c = strText.charAt(i);
            intAsc = (int) c;
            strHex = Integer.toHexString(intAsc);
            if (intAsc > 128) {
                str.append("\\u").append(strHex);
            } else // 低位在前面补00
            {
                str.append("\\u00").append(strHex);
            }
        }
        return str.toString();
    }

    /**
     * unicode的String转换成String的字符串
     *
     * @param hex 16进制值字符串 （一个unicode为2byte）
     * @return String 全角字符串
     */
    public static String unicodeToString(String hex) {
        int t = hex.length() / 6;
        StringBuilder str = new StringBuilder();
        for (int i = 0; i < t; i++) {
            String s = hex.substring(i * 6, (i + 1) * 6);
            // 高位需要补上00再转
            String s1 = s.substring(2, 4) + "00";
            // 低位直接转
            String s2 = s.substring(4);
            // 将16进制的string转为int
            int n = Integer.valueOf(s1, HEX_16) + Integer.valueOf(s2, HEX_16);
            // 将int转换为字符
            char[] chars = Character.toChars(n);
            str.append(new String(chars));
        }
        return str.toString();
    }

    /**
     * 字节转十六进制
     *
     * @param b 需要进行转换的byte字节
     * @return 转换后的Hex字符串
     */
    public static String byteToHex(byte b) {
        String hex = Integer.toHexString(b & 0xFF);
        if (hex.length() < 2) {
            hex = "0" + hex;
        }
        return hex;
    }

    /**
     * 字节数组转16进制
     *
     * @param bytes 需要转换的byte数组
     * @return 转换后的Hex字符串
     */
    public static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte aByte : bytes) {
            String hex = Integer.toHexString(aByte & 0xFF);
            if (hex.length() < 2) {
                sb.append(0);
            }
            sb.append(hex);
        }
        return sb.toString();
    }

    /**
     * ByteBuf数组转16进制浮点数
     *
     * @param buf
     * @param scale 需要保留的小数位个数
     * @return
     */
    public static Double hexBuf2Float(ByteBuf buf, int scale) {
        short[] b = new short[4];
        b[2] = buf.isReadable() ? buf.readUnsignedByte() : 0;
        b[3] = buf.isReadable() ? buf.readUnsignedByte() : 0;
        b[0] = buf.isReadable() ? buf.readUnsignedByte() : 0;
        b[1] = buf.isReadable() ? buf.readUnsignedByte() : 0;
        StringBuilder buffer = new StringBuilder();
        for (Short s : b) {
            buffer.append(Integer.toHexString(s.intValue()));
        }
        long l = Long.parseLong(buffer.toString(), HEX_16);
        float f = Float.intBitsToFloat((int) l);
        BigDecimal decimal = new BigDecimal(f);
        return decimal.setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    public static short deviceId(ByteBuf byteBuf) {
        // 获取第一个字符
        int index = byteBuf.getByte(byteBuf.readerIndex());
        log.info(Integer.toHexString(index));
        return 0;
    }

}
